"""
Token系统

定义依赖注入的Token类型，用于标识和获取依赖。
"""

from typing import TypeVar, Generic, Type, Any, Union
from abc import ABC, abstractmethod

T = TypeVar('T')


class Token(Generic[T], ABC):
    """
    依赖注入Token抽象基类
    
    Token用于唯一标识一个依赖项，支持类型安全的依赖注入。
    """
    
    def __init__(self, name: str, type_hint: Type[T] = None):
        self.name = name
        self.type_hint = type_hint
    
    @abstractmethod
    def __eq__(self, other) -> bool:
        """Token相等性比较"""
        pass
    
    @abstractmethod
    def __hash__(self) -> int:
        """Token哈希值"""
        pass
    
    def __str__(self) -> str:
        return f"Token({self.name})"
    
    def __repr__(self) -> str:
        return self.__str__()


class StringToken(Token[T]):
    """
    字符串Token实现
    
    使用字符串作为Token标识符的简单实现。
    """
    
    def __init__(self, name: str, type_hint: Type[T] = None):
        super().__init__(name, type_hint)
    
    def __eq__(self, other) -> bool:
        if not isinstance(other, StringToken):
            return False
        return self.name == other.name
    
    def __hash__(self) -> int:
        return hash(self.name)


class ClassToken(Token[T]):
    """
    类Token实现
    
    使用类型作为Token标识符的实现。
    """
    
    def __init__(self, cls: Type[T]):
        super().__init__(cls.__name__, cls)
        self.cls = cls
    
    def __eq__(self, other) -> bool:
        if not isinstance(other, ClassToken):
            return False
        return self.cls == other.cls
    
    def __hash__(self) -> int:
        return hash(self.cls)
    
    def __str__(self) -> str:
        return f"ClassToken({self.cls.__name__})"


class QualifiedToken(Token[T]):
    """
    限定Token实现
    
    支持带限定符的Token，用于区分同一类型的不同实例。
    """
    
    def __init__(self, cls: Type[T], qualifier: str):
        super().__init__(f"{cls.__name__}#{qualifier}", cls)
        self.cls = cls
        self.qualifier = qualifier
    
    def __eq__(self, other) -> bool:
        if not isinstance(other, QualifiedToken):
            return False
        return self.cls == other.cls and self.qualifier == other.qualifier
    
    def __hash__(self) -> int:
        return hash((self.cls, self.qualifier))
    
    def __str__(self) -> str:
        return f"QualifiedToken({self.cls.__name__}#{self.qualifier})"


class GenericToken(Token[T]):
    """
    泛型Token

    用于表示泛型类型，如List[str]、Dict[str, Any]等。
    """

    def __init__(self, generic_type):
        import typing

        # 获取泛型的origin和args
        self.generic_type = generic_type
        self.origin = typing.get_origin(generic_type)
        self.args = typing.get_args(generic_type)

        # 生成名称
        name = str(generic_type)
        super().__init__(name, generic_type)

    def __eq__(self, other) -> bool:
        if not isinstance(other, GenericToken):
            return False
        return self.generic_type == other.generic_type

    def __hash__(self) -> int:
        return hash(self.generic_type)

    def __str__(self) -> str:
        return f"GenericToken({self.generic_type})"


# Token工厂函数
def create_token(identifier: Union[str, Type[T], Token[T]], qualifier: str = None) -> Token[T]:
    """
    创建Token的工厂函数

    Args:
        identifier: 字符串标识符、类型、泛型类型或现有Token
        qualifier: 可选的限定符

    Returns:
        对应的Token实例
    """
    if isinstance(identifier, str):
        return StringToken(identifier)
    elif isinstance(identifier, type):
        if qualifier:
            return QualifiedToken(identifier, qualifier)
        else:
            return ClassToken(identifier)
    elif isinstance(identifier, Token):
        # 从现有Token创建Token - 直接返回原Token（Token是不可变的）
        return identifier
    elif _is_generic_type(identifier):
        # 泛型类型（如List[str], Dict[str, Any]等）
        return GenericToken(identifier)
    else:
        raise ValueError(f"不支持的Token标识符类型: {type(identifier)}")


def _is_generic_type(obj) -> bool:
    """
    检查对象是否为泛型类型

    Args:
        obj: 要检查的对象

    Returns:
        如果是泛型类型返回True，否则返回False
    """
    import typing

    # 检查是否有__origin__属性（泛型类型的标志）
    if hasattr(obj, '__origin__'):
        return True

    # 使用typing.get_origin()进行更可靠的检查
    try:
        origin = typing.get_origin(obj)
        return origin is not None
    except (TypeError, AttributeError):
        return False


# 预定义的常用Token
class CommonTokens:
    """常用Token定义"""
    
    # 配置相关
    CONFIG = StringToken("config")
    LOGGER = StringToken("logger")
    
    # 数据库相关
    DATABASE = StringToken("database")
    CONNECTION = StringToken("connection")
    
    # 缓存相关
    CACHE = StringToken("cache")
    REDIS = StringToken("redis")
    
    # 消息队列
    MESSAGE_QUEUE = StringToken("message_queue")
    
    # 文件系统
    FILE_SYSTEM = StringToken("file_system")
    TEMP_DIR = StringToken("temp_dir")
    
    # HTTP客户端
    HTTP_CLIENT = StringToken("http_client")
    
    # 事件总线
    EVENT_BUS = StringToken("event_bus")


# 类型别名，用于更好的类型提示
AnyToken = Token[Any]
ConfigToken = Token[dict]
LoggerToken = Token[Any]  # 实际应该是Logger类型


class TokenRegistry:
    """
    Token注册表
    
    管理全局的Token定义，支持Token的注册、查找和验证。
    """
    
    def __init__(self):
        self._tokens: dict[str, Token] = {}
        self._register_common_tokens()
    
    def register(self, token: Token) -> None:
        """注册Token"""
        self._tokens[token.name] = token
    
    def get(self, name: str) -> Token:
        """获取Token"""
        token = self._tokens.get(name)
        if not token:
            raise KeyError(f"未找到Token: {name}")
        return token
    
    def exists(self, name: str) -> bool:
        """检查Token是否存在"""
        return name in self._tokens
    
    def list_tokens(self) -> list[str]:
        """列出所有Token名称"""
        return list(self._tokens.keys())
    
    def unregister(self, name: str) -> bool:
        """注销Token"""
        if name in self._tokens:
            del self._tokens[name]
            return True
        return False
    
    def _register_common_tokens(self) -> None:
        """注册常用Token"""
        for attr_name in dir(CommonTokens):
            if not attr_name.startswith('_'):
                token = getattr(CommonTokens, attr_name)
                if isinstance(token, Token):
                    self.register(token)


# 全局Token注册表
token_registry = TokenRegistry()


class TokenBuilder:
    """
    Token构建器
    
    提供流式API来构建复杂的Token。
    """
    
    def __init__(self):
        self._name: str = ""
        self._type_hint: Type = None
        self._qualifier: str = None
    
    def name(self, name: str) -> 'TokenBuilder':
        """设置Token名称"""
        self._name = name
        return self
    
    def type(self, type_hint: Type[T]) -> 'TokenBuilder':
        """设置Token类型"""
        self._type_hint = type_hint
        return self
    
    def qualifier(self, qualifier: str) -> 'TokenBuilder':
        """设置Token限定符"""
        self._qualifier = qualifier
        return self
    
    def build(self) -> Token:
        """构建Token"""
        if not self._name and not self._type_hint:
            raise ValueError("必须指定Token名称或类型")
        
        if self._type_hint:
            if self._qualifier:
                return QualifiedToken(self._type_hint, self._qualifier)
            else:
                return ClassToken(self._type_hint)
        else:
            return StringToken(self._name, self._type_hint)


def token_builder() -> TokenBuilder:
    """创建Token构建器"""
    return TokenBuilder()


# 装饰器用的Token标记
class InjectToken:
    """
    注入Token标记
    
    用于在装饰器中标记需要注入的参数。
    """
    
    def __init__(self, token: Token):
        self.token = token
    
    def __str__(self) -> str:
        return f"InjectToken({self.token})"
    
    def __repr__(self) -> str:
        return self.__str__()


def inject_token(token: Union[str, Type[T], Token[T]]) -> InjectToken:
    """
    创建注入Token标记
    
    Args:
        token: Token标识符、类型或Token实例
    
    Returns:
        InjectToken标记
    """
    if isinstance(token, Token):
        return InjectToken(token)
    else:
        return InjectToken(create_token(token))


# 便捷函数
def string_token(name: str) -> StringToken:
    """创建字符串Token"""
    return StringToken(name)


def class_token(cls: Type[T]) -> ClassToken[T]:
    """创建类Token"""
    return ClassToken(cls)


def qualified_token(cls: Type[T], qualifier: str) -> QualifiedToken[T]:
    """创建限定Token"""
    return QualifiedToken(cls, qualifier)
